home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / proc / procExec.c < prev    next >
C/C++ Source or Header  |  1991-07-26  |  59KB  |  2,001 lines

  1. /* procExec.c --
  2.  *
  3.  *    Routines to exec a program.  There is no monitor required in this
  4.  *    file.  Access to the proc table is synchronized by locking the PCB
  5.  *    when modifying the genFlags field.
  6.  *
  7.  * Copyright (C) 1985, 1988 Regents of the University of California
  8.  * Permission to use, copy, modify, and distribute this
  9.  * software and its documentation for any purpose and without
  10.  * fee is hereby granted, provided that the above copyright
  11.  * notice appear in all copies.  The University of California
  12.  * makes no representations about the suitability of this
  13.  * software for any purpose.  It is provided "as is" without
  14.  * express or implied warranty.
  15.  */
  16.  
  17. #ifndef lint
  18. static char rcsid[] = "$Header: /sprite/src/kernel/proc/RCS/procExec.c,v 9.29 91/07/26 16:59:33 shirriff Exp $ SPRITE (Berkeley)";
  19. #endif /* not lint */
  20.  
  21. #include <sprite.h>
  22. #include <procMach.h>
  23. #include <mach.h>
  24. #include <proc.h>
  25. #include <procInt.h>
  26. #include <sync.h>
  27. #include <sched.h>
  28. #include <fs.h>
  29. #include <fsio.h>
  30. #include <stdlib.h>
  31. #include <sig.h>
  32. #include <spriteTime.h>
  33. #include <list.h>
  34. #include <vm.h>
  35. #include <sys.h>
  36. #include <procMigrate.h>
  37. #include <procUnixStubs.h>
  38. #include <status.h>
  39. #include <string.h>
  40. #include <byte.h>
  41. #include <rpc.h>
  42. #include <prof.h>
  43. #include <fsutil.h>
  44. #include <ctype.h>
  45. #include <stdio.h>
  46. #include <bstring.h>
  47. #include <vmMach.h>
  48. #include <file.h>
  49. /*
  50.  * This will go away when libc is changed.
  51.  */
  52. #ifndef PROC_MAX_ENVIRON_LENGTH
  53. #define PROC_MAX_ENVIRON_LENGTH (PROC_MAX_ENVIRON_NAME_LENGTH + \
  54.                  PROC_MAX_ENVIRON_VALUE_LENGTH)
  55. #endif /*  PROC_MAX_ENVIRON_LENGTH */
  56.  
  57. #define UNIX_CODE 1
  58.  
  59. typedef struct {
  60.     List_Links    links;
  61.     Address    stringPtr;
  62.     int        stringLen;
  63. } ArgListElement;
  64.  
  65. extern int debugProcStubs;
  66.  
  67. /*
  68.  * Define the information needed to perform an exec: the user's stack,
  69.  * where to put it, and whether to debug on startup.  We define a structure
  70.  * containing the "meta-info" that isn't actually copied onto the user's
  71.  * stack, and then another structure that also includes argc.  (By
  72.  * separating the header into a separate structure, it's easier to take its
  73.  * size.)
  74.  * 
  75.  * Note that the actual values for argv and envp passed to main() are
  76.  * calculated by _start() based on the address of argc and are not actually
  77.  * put on the stack given to the exec'ed process.  The size of the structure
  78.  * to be copied onto the user's stack is the size in the 'size' field
  79.  * minus the size of the header.
  80.  *
  81.  * The fileName and argString fields are used only when doing a remote exec.
  82.  */
  83. typedef struct {
  84.     Address base;        /* base of the structure in user space */
  85.     int size;            /* size of the entire structure */
  86.     char *fileName;        /* pointer to buffer containing name of file
  87.                  * to exec */
  88.     int fileNameLength;        /* length of file name buffer */
  89.     char *argString;        /* pointer to buffer containing full list of
  90.                  * arguments, for ps listing */
  91.     int argLength;        /* length of argString buffer */
  92. } ExecEncapHeader;
  93.  
  94. typedef struct {
  95.     ExecEncapHeader hdr;    /* meta-information; see above */
  96.     /*
  97.      * User stack data starts here.
  98.      */
  99.     int argc;            /* Number of arguments */
  100.     /*
  101.      * argv[] goes here
  102.      * envp[] goes here
  103.      * *argv[] goes here
  104.      * *envp[] goes here
  105.      */
  106. } ExecEncapState;
  107.  
  108. /*
  109.  * Define a structure to hold all the information about arguments
  110.  * and environment variables (pointer and length).  This makes it easier
  111.  * to pass a NIL pointer for the whole thing, and to keep them in one
  112.  * place.  The number of arguments/environment pointers includes the 
  113.  * null pointer at the end of the array.
  114.  */
  115.  
  116. typedef struct {
  117.     Boolean    userMode;    /* TRUE if the arguments are in user space */
  118.     char    **argPtrArray;    /* The array of argument pointers. */
  119.     int        numArgs;    /* The number of arguments in the argArray. */
  120.     int        argLength;    /* actual size of argArray */
  121.     char    **envPtrArray;    /* The array of environment pointers. */
  122.     int        numEnvs;    /* The number of arguments in the envArray. */
  123.     int        envLength;    /* actual size of envArray */
  124. } UserArgs;
  125.  
  126. /*
  127.  * Forward declarations.
  128.  */
  129. static ReturnStatus     DoExec _ARGS_((char fileName[], 
  130.                 UserArgs *userArgsPtr, 
  131.                 ExecEncapState **encapPtrPtr, Boolean debugMe));
  132. static ReturnStatus     SetupInterpret _ARGS_((register char *buffer, 
  133.                 int sizeRead, register Fs_Stream **filePtrPtr, 
  134.                 char **argPtrPtr, int *extraArgsPtr, 
  135.                 ProcObjInfo *objInfoPtr));
  136. static ReturnStatus     SetupArgs _ARGS_((UserArgs *userArgsPtr, 
  137.                 char **extraArgArray, Address *argStackPtr, 
  138.                 char **argStringPtr));
  139. static ReturnStatus     GrabArgArray _ARGS_((int maxLength, Boolean userProc, 
  140.                 char **extraArgArray, char **argPtrArray, 
  141.                 int *numArgsPtr, List_Links *argList, 
  142.                 int *realLengthPtr, int *paddedLengthPtr));
  143. static Boolean         SetupVM _ARGS_((register Proc_ControlBlock *procPtr, 
  144.                 register ProcObjInfo *objInfoPtr, 
  145.                 Fs_Stream *codeFilePtr, Boolean usedFile, 
  146.                 Vm_Segment **codeSegPtrPtr, 
  147.                 register Vm_ExecInfo *execInfoPtr));
  148. static Boolean        ZeroHeapEnd _ARGS_ ((Vm_ExecInfo *execInfoPtr));
  149.  
  150. #ifdef notdef
  151. /*
  152.  * Define a type to include the information that is passed from
  153.  * the local setup routine to the routine that performs the actual
  154.  * exec.
  155.  */
  156. typedef struct {
  157.     Proc_AOUT                *aoutPtr;
  158.     Vm_ExecInfo                *execInfoPtr;
  159.     Proc_AOUT                aout;
  160.     Vm_Segment                *codeSegPtr = (Vm_Segment *) NIL;
  161.     char                *argString = (char *) NIL;
  162.     Address                argBuffer = (Address) NIL;
  163.     Fs_Stream                *filePtr;
  164.     int                    entry;
  165.     Boolean                usedFile;
  166.     int                    uid;
  167.     int                    gid;
  168.     ExecEncapState            *hdrPtr;
  169. }
  170. #endif    
  171.  
  172. /*
  173.  * Define entry points for exec.  They are distinct due to compatibility
  174.  * considerations.  We can deal with them better when we convert the
  175.  * system calls to be more unix-like.
  176.  */
  177.  
  178. /*
  179.  *----------------------------------------------------------------------
  180.  *
  181.  * Proc_RemoteExec --
  182.  *
  183.  *    Process the Exec system call on a remote host.
  184.  *    This does the same setup as Proc_Exec, and then initiates a migration
  185.  *    with the stack of the new process contained in a buffer reachable
  186.  *    from the process control block.
  187.  *
  188.  * Results:
  189.  *    SUCCESS indicates that the process has been signalled to cause it
  190.  *    to migrate before it exits the kernel.  Any other status is
  191.  *    an error that should be returned to the process as usual.
  192.  *
  193.  * Side effects:
  194.  *    Memory is allocated for the buffer containing the exec info.
  195.  *    This should be freed by the migration encapsulation routine.
  196.  *
  197.  *----------------------------------------------------------------------
  198.  */
  199.  
  200. int
  201. Proc_RemoteExec(fileName, argPtrArray, envPtrArray, host)
  202.     char    *fileName;    /* The name of the file to exec. */
  203.     char    **argPtrArray;    /* The array of arguments to the exec'd 
  204.                  * program. */
  205.     char    **envPtrArray;    /* The array of environment variables for
  206.                  * the exec'd program. */
  207.     int        host;        /* ID of host on which to exec. */
  208. {
  209.     int status;
  210.     
  211.     /*
  212.      * XXX need to check permission to migrate.
  213.      */
  214.  
  215.     status = Proc_Exec(fileName, argPtrArray, envPtrArray, FALSE, host);
  216.     /*
  217.      * XXX on failure, need to clean up.
  218.      */
  219.     return(status);
  220. }
  221.  
  222.  
  223. /*
  224.  *----------------------------------------------------------------------
  225.  *
  226.  * Proc_ExecEnv --
  227.  *
  228.  *    Here for backward compatibility.  It does an exec on the
  229.  *    local host.
  230.  *
  231.  * Results:
  232.  *    This process will not return unless an error occurs in which case it
  233.  *    returns the error.
  234.  *
  235.  * Side effects:
  236.  *    None.
  237.  *
  238.  *----------------------------------------------------------------------
  239.  */
  240.  
  241. int
  242. Proc_ExecEnv(fileName, argPtrArray, envPtrArray, debugMe)
  243.     char    *fileName;    /* The name of the file to exec. */
  244.     char    **argPtrArray;    /* The array of arguments to the exec'd 
  245.                  * program. */
  246.     char    **envPtrArray;    /* The array of environment variables
  247.                  * of the form NAME=VALUE. */ 
  248.     Boolean    debugMe;    /* TRUE means that the process is 
  249.                  * to be sent a SIG_DEBUG signal before
  250.                      * executing its first instruction. */
  251. {
  252.     return(Proc_Exec(fileName, argPtrArray, envPtrArray, debugMe, 0));
  253. }
  254.  
  255.  
  256. /*
  257.  *----------------------------------------------------------------------
  258.  *
  259.  * Proc_Exec --
  260.  *
  261.  *    The ultimate entry point for the Exec system call.  This
  262.  *     handles both local and remote exec's.  It calls SetupExec to
  263.  *     initialize the file pointer, a.out info, user's stack image, etc.
  264.  *    The a.out information is used if the exec is
  265.  *     performed on this machine, but for a remote exec, the file
  266.  *    is reopened in case of different machine types.  The stack is
  267.  *     used locally or copied to the remote host.
  268.  *
  269.  * Results:
  270.  *    For local exec's, this procedure will not return unless an error
  271.  *    occurs, in which case it returns the error.  For remote exec's,
  272.  *    SUCCESS is returned, and the calling routine arranges for
  273.  *    the process to hit a migration signal before continuing.
  274.  *
  275.  * Side effects:
  276.  *    The argument & environment arrays are made accessible.  Memory
  277.  *    is allocated for the file name.  
  278.  *    The DoExec routine makes the arrays unaccessible.  It frees the
  279.  *    space for the file name, unless the name is used for a remote
  280.  *    exec, in which case it is left around until after migration.
  281.  *
  282.  *----------------------------------------------------------------------
  283.  */
  284.  
  285. int
  286. Proc_Exec(fileName, argPtrArray, envPtrArray, debugMe, host)
  287.     char    *fileName;    /* The name of the file to exec. */
  288.     char    **argPtrArray;    /* The array of arguments to the exec'd 
  289.                  * program. */
  290.     char    **envPtrArray;    /* The array of environment variables
  291.                  * of the form NAME=VALUE. */ 
  292.     Boolean    debugMe;    /* TRUE means that the process is 
  293.                  * to be sent a SIG_DEBUG signal before
  294.                      * executing its first instruction. */
  295.     int        host;        /* Host to which to do remote exec, or 0
  296.                  * for local host. */
  297. {
  298.     char        **newArgPtrArray;
  299.     int            newArgPtrArrayLength;
  300.     char        **newEnvPtrArray;
  301.     int            newEnvPtrArrayLength;
  302.     UserArgs        userArgs;
  303.     int            strLength;
  304.     int            accessLength;
  305.     ReturnStatus    status;
  306.     char         *execFileName;
  307.     ExecEncapState    *encapPtr;
  308.     ExecEncapState    **encapPtrPtr;
  309.     Proc_ControlBlock     *procPtr;
  310.     
  311.  
  312.  
  313.     /*
  314.      * Make the file name accessible. 
  315.      */
  316.  
  317.     status = Proc_MakeStringAccessible(FS_MAX_PATH_NAME_LENGTH, &fileName,
  318.                        &accessLength, &strLength);
  319.     if (status != SUCCESS) {
  320.     return(status);
  321.     }
  322.  
  323.     execFileName = malloc(accessLength);
  324.     (void) strncpy(execFileName, fileName, accessLength);
  325.     Proc_MakeUnaccessible((Address) fileName, accessLength);
  326.  
  327.     /*
  328.      * Make the arguments array accessible.
  329.      */
  330.  
  331.     if (argPtrArray != (char **) USER_NIL) {
  332.     Vm_MakeAccessible(VM_READONLY_ACCESS,
  333.               (PROC_MAX_EXEC_ARGS + 1) * sizeof(Address),
  334.               (Address) argPtrArray, 
  335.                   &newArgPtrArrayLength, (Address *) &newArgPtrArray);
  336.     if (newArgPtrArrayLength == 0) {
  337.         return(SYS_ARG_NOACCESS);
  338.     }
  339.     } else {
  340.     newArgPtrArray = (char **) NIL;
  341.     newArgPtrArrayLength = 0;
  342.     }
  343.  
  344.     /*
  345.      * Make the environments array accessible.
  346.      */
  347.  
  348.     if (envPtrArray != (char **) USER_NIL) {
  349.     Vm_MakeAccessible(VM_READONLY_ACCESS,
  350.               (PROC_MAX_ENVIRON_SIZE + 1) * sizeof(Address),
  351.               (Address) envPtrArray, 
  352.                   &newEnvPtrArrayLength, (Address *) &newEnvPtrArray);
  353.     if (newEnvPtrArrayLength == 0) {
  354.         return(SYS_ARG_NOACCESS);
  355.     }
  356.     } else {
  357.     newEnvPtrArray = (char **) NIL;
  358.     newEnvPtrArrayLength = 0;
  359.     }
  360.     /*
  361.      * Perform the exec, if local, or setup the user's stack if remote.
  362.      */
  363.     userArgs.userMode = TRUE;
  364.     userArgs.argPtrArray = newArgPtrArray;
  365.     userArgs.numArgs = newArgPtrArrayLength / sizeof(Address);
  366.     userArgs.argLength = newArgPtrArrayLength;
  367.     userArgs.envPtrArray = newEnvPtrArray;
  368.     userArgs.numEnvs = newEnvPtrArrayLength / sizeof(Address);
  369.     userArgs.envLength = newEnvPtrArrayLength;
  370.  
  371.     /*
  372.      * Check for explicit remote exec onto this host, in which case it's
  373.      * a local exec.
  374.      */
  375.     if (host == rpc_SpriteID) {
  376.     host = 0;
  377.     }
  378.  
  379.     if (host != 0) {
  380.     encapPtrPtr = &encapPtr;
  381.     } else {
  382.     encapPtrPtr = (ExecEncapState **) NIL;
  383.     }
  384.     status = DoExec(execFileName, &userArgs, encapPtrPtr, debugMe);
  385.     if (status == SUCCESS) {
  386.     if (host != 0) {
  387.         /*
  388.          * Set up the process to migrate.
  389.          */
  390.         procPtr = Proc_GetCurrentProc();
  391.         Proc_Lock(procPtr);
  392.         status = ProcInitiateMigration(procPtr, host);
  393.         if (status == SUCCESS) {
  394.         procPtr->remoteExecBuffer = (Address) encapPtr;
  395.         Proc_FlagMigration(procPtr, host, TRUE);
  396.         } else {
  397.         free((Address) encapPtr);
  398.         }
  399.         Proc_Unlock(procPtr);
  400.     } else {
  401.         panic("Proc_Exec: DoExec returned SUCCESS!!!\n");
  402.     }
  403.     }
  404.     return(status);
  405. }
  406.  
  407.  
  408. /*
  409.  *----------------------------------------------------------------------
  410.  *
  411.  * Proc_KernExec --
  412.  *
  413.  *    Do an exec from a kernel process.  This will exec the program and
  414.  *    change the type of process to a user process.
  415.  *
  416.  * Results:
  417.  *    This routine does not return unless an error occurs from DoExec.
  418.  *
  419.  * Side effects:
  420.  *    None.
  421.  *
  422.  *----------------------------------------------------------------------
  423.  */
  424.  
  425. /* 
  426.  * Use the old Proc_KernExec until this gets installed as the sole procExec.c.
  427.  */
  428. int
  429. Proc_KernExec(fileName, argPtrArray)
  430.     char *fileName;
  431.     char **argPtrArray;
  432. {
  433.     register    Proc_ControlBlock    *procPtr;
  434.     ReturnStatus            status;
  435.     UserArgs                userArgs;
  436.  
  437.     procPtr = Proc_GetCurrentProc();
  438.  
  439.     /*
  440.      * Set up dummy segments so that DoExec can work properly.
  441.      */
  442.  
  443.     procPtr->vmPtr->segPtrArray[VM_CODE] = 
  444.                 Vm_SegmentNew(VM_CODE, (Fs_Stream *) NIL, 0,
  445.                               1, 0, procPtr);
  446.     if (procPtr->vmPtr->segPtrArray[VM_CODE] == (Vm_Segment *) NIL) {
  447.     return(PROC_NO_SEGMENTS);
  448.     }
  449.  
  450.     procPtr->vmPtr->segPtrArray[VM_HEAP] =
  451.             Vm_SegmentNew(VM_HEAP, (Fs_Stream *) NIL, 0, 1, 1, procPtr);
  452.     if (procPtr->vmPtr->segPtrArray[VM_HEAP] == (Vm_Segment *) NIL) {
  453.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_CODE], procPtr);
  454.     return(PROC_NO_SEGMENTS);
  455.     }
  456.  
  457.     procPtr->vmPtr->segPtrArray[VM_STACK] =
  458.             Vm_SegmentNew(VM_STACK, (Fs_Stream *) NIL, 
  459.                    0 , 1, mach_LastUserStackPage, procPtr);
  460.     if (procPtr->vmPtr->segPtrArray[VM_STACK] == (Vm_Segment *) NIL) {
  461.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_CODE], procPtr);
  462.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_HEAP], procPtr);
  463.     return(PROC_NO_SEGMENTS);
  464.     }
  465.  
  466.     /*
  467.      * Change this process to a user process.
  468.      */
  469.  
  470.     Proc_Lock(procPtr);
  471.     procPtr->genFlags &= ~PROC_KERNEL;
  472.     procPtr->genFlags |= PROC_USER;
  473.     Proc_Unlock(procPtr);
  474.  
  475.     VmMach_ReinitContext(procPtr);
  476.  
  477.     userArgs.userMode = FALSE;
  478.     userArgs.argPtrArray = argPtrArray;
  479.     userArgs.numArgs = PROC_MAX_EXEC_ARGS;
  480.     userArgs.argLength = PROC_MAX_EXEC_ARGS * sizeof(Address);
  481.     userArgs.envPtrArray = (char **) NIL;
  482.     userArgs.numEnvs = 0;
  483.     userArgs.envLength = 0;
  484.     status = DoExec(fileName, &userArgs, (ExecEncapState **) NIL, FALSE);
  485.     /*
  486.      * If the exec failed, then delete the extra segments and fix up the
  487.      * proc table entry to put us back into kernel mode.
  488.      */
  489.  
  490.     Proc_Lock(procPtr);
  491.     procPtr->genFlags &= ~PROC_USER;
  492.     procPtr->genFlags |= PROC_KERNEL;
  493.     Proc_Unlock(procPtr);
  494.  
  495.     VmMach_ReinitContext(procPtr);
  496.  
  497.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_CODE], procPtr);
  498.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_HEAP], procPtr);
  499.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_STACK], procPtr);
  500.  
  501.     return(status);
  502. }
  503.  
  504.  
  505. /*
  506.  *----------------------------------------------------------------------
  507.  *
  508.  * SetupArgs --
  509.  *
  510.  *    Chase through arrays of character strings (usually in user space)
  511.  *    and copy them into a contiguous array.  This array is later copied
  512.  *    onto the stack of the exec'd program, and it may be used to
  513.  *    pass the arguments to another host for a remote exec.  It
  514.  *    contains argc, argv, envp, and the strings referenced by argv and
  515.  *    envp.  All values in argv and envp are relative to the presumed
  516.  *    start of the data in user space, which is normally set up to end at
  517.  *    mach_MaxUserStackAddr.  If
  518.  *    the exec is performed on a different machine, the pointers in argv and
  519.  *    envp must be adjusted by the relative values of mach_MaxUserStackAddr.
  520.  *
  521.  *    The format of the structure is defined by ExecEncapState above.
  522.  *        
  523.  *
  524.  * Results:
  525.  *    A ReturnStatus is returned.  Any non-SUCCESS result indicates a failure
  526.  *    that should be returned to the user.
  527.  *    In addition, a pointer to the encapsulated stack is returned,
  528.  *    as well as its size.
  529.  *
  530.  * Side effects:
  531.  *    Memory is allocated for the argument stack.
  532.  *
  533.  *----------------------------------------------------------------------
  534.  */
  535.  
  536. static ReturnStatus
  537. SetupArgs(userArgsPtr, extraArgArray, argStackPtr, argStringPtr)
  538.     UserArgs *userArgsPtr;    /* Information for taking args
  539.                  * and environment. */ 
  540.     char     **extraArgArray;    /* Any arguments that should be
  541.                        * inserted prior to argv[1] */
  542.     Address  *argStackPtr;     /* Pointer to contain address of encapsulated
  543.                  * stack. */
  544.     char     **argStringPtr;    /* Pointer to allocated buffer for argument
  545.                  * list as a single string (for ps) */
  546. {
  547.     int         numArgs;        /* The number of arguments in the argArray. */
  548.     int         numEnvs;        /* The number of arguments in the envArray. */
  549.     register    ArgListElement        *argListPtr;
  550.     register    int            argNumber;
  551.     char                **newArgPtrArray;
  552.     char                **newEnvPtrArray;
  553.     List_Links                argList;
  554.     List_Links                envList;
  555.     char                *argBuffer;
  556.     char                *envBuffer;
  557.     register    char            *argString;
  558.     int                    argStringLength;
  559.     ReturnStatus            status;
  560.     int                    usp;
  561.     int                    paddedArgLength;
  562.     int                    paddedEnvLength;
  563.     int                    bufSize;
  564.     Address                buffer;
  565.     int                    stackSize;
  566.     ExecEncapHeader            *hdrPtr;
  567.     ExecEncapState            *encapPtr;
  568.  
  569.     /*
  570.      * Initialize variables so when if we abort we know what to clean up.
  571.      */
  572.     *argStringPtr = (char *) NIL;
  573.     
  574.     List_Init(&argList);
  575.     List_Init(&envList);
  576.  
  577.     /*
  578.      * Copy in the arguments.  argStringLength is an upper bound on
  579.      * the total length permitted.
  580.      */
  581.     numArgs = userArgsPtr->numArgs;
  582.     argStringLength = PROC_MAX_EXEC_ARG_LENGTH;
  583.     status = GrabArgArray(PROC_MAX_EXEC_ARG_LENGTH + 1,
  584.               userArgsPtr->userMode, extraArgArray,
  585.               userArgsPtr->argPtrArray, &numArgs,
  586.               &argList, &argStringLength,
  587.               &paddedArgLength);
  588.  
  589.  
  590.     if (status != SUCCESS) {
  591.     goto execError;
  592.     }
  593.     /*
  594.      * Copy in the environment.
  595.      */
  596.  
  597.     numEnvs = userArgsPtr->numEnvs;
  598.     status = GrabArgArray(PROC_MAX_ENVIRON_LENGTH + 1,
  599.               userArgsPtr->userMode, (char **) NIL,
  600.               userArgsPtr->envPtrArray, &numEnvs,
  601.               &envList, (int *) NIL,
  602.               &paddedEnvLength);
  603.  
  604.     if (status != SUCCESS) {
  605.     goto execError;
  606.     }
  607.  
  608.     /*
  609.      * Now copy all of the arguments and environment variables into a buffer.
  610.      * Allocate the buffer and initialize pointers into it.
  611.      * The stack ends up in the following state:  the top word is argc.
  612.      * Right below this is the array of pointers to arguments (argv).  Right
  613.      * below this is the array of pointers to environment stuff (envp).  So,
  614.      * to figure out the address of argv, one simply adds a word to the address
  615.      * of the top of the stack.  To figure out the address of envp, one
  616.      * looks at argc and skips over the appropriate amount of space to jump
  617.      * over argc and argv = (1 + (argc + 1)) * 4 bytes.  The extra "1" is for
  618.      * the null argument at the end of argv.  Below all that stuff on the
  619.      * stack come the environment and argument strings themselves.
  620.      */
  621.     bufSize = sizeof(ExecEncapState) + (numArgs + numEnvs + 2) * sizeof(Address)
  622.     + paddedArgLength + paddedEnvLength;
  623.     buffer = malloc(bufSize);
  624.     *argStackPtr = buffer;
  625.     encapPtr = (ExecEncapState *) buffer;
  626.     hdrPtr = &encapPtr->hdr;
  627.     hdrPtr->size = bufSize;
  628.     stackSize = Byte_AlignAddr((bufSize - sizeof(ExecEncapHeader)));
  629.     hdrPtr->base = mach_MaxUserStackAddr - stackSize;
  630.     encapPtr->argc = numArgs;
  631.     newArgPtrArray = (char **) (buffer + sizeof(ExecEncapState));
  632.     newEnvPtrArray = (char **) ((int) newArgPtrArray +
  633.                 (numArgs + 1) * sizeof(Address));
  634.     argBuffer = (Address) ((int) newEnvPtrArray +
  635.                (numEnvs + 1) * sizeof(Address));
  636.     envBuffer =  (argBuffer + paddedArgLength);
  637.                 
  638.     argNumber = 0;
  639.     usp = (int)hdrPtr->base + (int) argBuffer - (int) &encapPtr->argc;
  640.     argString = malloc(argStringLength + 1);
  641.     *argStringPtr = argString;
  642.  
  643.     while (!List_IsEmpty(&argList)) {
  644.     argListPtr = (ArgListElement *) List_First(&argList);
  645.     /*
  646.      * Copy the argument.
  647.      */
  648.     bcopy((Address) argListPtr->stringPtr, (Address) argBuffer,
  649.             argListPtr->stringLen);
  650.     newArgPtrArray[argNumber] = (char *) usp;
  651.     argBuffer += Byte_AlignAddr(argListPtr->stringLen);
  652.     usp += Byte_AlignAddr(argListPtr->stringLen);
  653.     bcopy((Address) argListPtr->stringPtr, argString,
  654.             argListPtr->stringLen - 1);
  655.     argString[argListPtr->stringLen - 1] = ' ';
  656.     argString += argListPtr->stringLen;
  657.     /*
  658.      * Clean up
  659.      */
  660.     List_Remove((List_Links *) argListPtr);
  661.     free((Address) argListPtr->stringPtr);
  662.     free((Address) argListPtr);
  663.     argNumber++;
  664.     }
  665.     argString[0] = '\0';
  666.     newArgPtrArray[argNumber] = (char *) USER_NIL;
  667.     
  668.     argNumber = 0;
  669.     while (!List_IsEmpty(&envList)) {
  670.     argListPtr = (ArgListElement *) List_First(&envList);
  671.     /*
  672.      * Copy the environment variable.
  673.      */
  674.     bcopy((Address) argListPtr->stringPtr, (Address) envBuffer,
  675.             argListPtr->stringLen);
  676.     newEnvPtrArray[argNumber] = (char *) usp;
  677.     envBuffer += Byte_AlignAddr(argListPtr->stringLen);
  678.     usp += Byte_AlignAddr(argListPtr->stringLen);
  679.     /*
  680.      * Clean up
  681.      */
  682.     List_Remove((List_Links *) argListPtr);
  683.     free((Address) argListPtr->stringPtr);
  684.     free((Address) argListPtr);
  685.     argNumber++;
  686.     }
  687.     newEnvPtrArray[argNumber] = (char *) USER_NIL;
  688.  
  689.     /*
  690.      * We're done here.  Leave it to the caller to free the copy of the
  691.      * stack after copying it to user space.
  692.      */
  693.     return(SUCCESS);
  694.     
  695. execError:
  696.     /*
  697.      * The exec failed while copying in the arguments.  Free any
  698.      * arguments or environment variables that were copied in.
  699.      */
  700.     while (!List_IsEmpty(&argList)) {
  701.     argListPtr = (ArgListElement *) List_First(&argList);
  702.     List_Remove((List_Links *) argListPtr);
  703.     free((Address) argListPtr->stringPtr);
  704.     free((Address) argListPtr);
  705.     }
  706.     while (!List_IsEmpty(&envList)) {
  707.     argListPtr = (ArgListElement *) List_First(&envList);
  708.     List_Remove((List_Links *) argListPtr);
  709.     free((Address) argListPtr->stringPtr);
  710.     free((Address) argListPtr);
  711.     }
  712.     return(status);
  713.  
  714. }
  715.  
  716.  
  717. /*
  718.  *----------------------------------------------------------------------
  719.  *
  720.  * GrabArgArray --
  721.  *
  722.  *    Copy a an array of strings from user space and put it in a
  723.  *    linked list of strings.  The terminology for "args" refers
  724.  *    to argv, but the same routine is used for environment variables
  725.  *    as well.
  726.  *
  727.  * Results:
  728.  *    A ReturnStatus indicates any sort of error, indicating immediate
  729.  *    failure that should be reported to the user.  Otherwise, the
  730.  *    arguments and their lengths are returned in the linked list
  731.  *    referred to by argListPtr, and the total length is returned
  732.  *    in *totalLengthPtr.
  733.  *
  734.  * Side effects:
  735.  *    Memory is allocated to hold the strings and the structures
  736.  *    pointing to them.
  737.  *
  738.  *----------------------------------------------------------------------
  739.  */
  740.  
  741. static ReturnStatus
  742. GrabArgArray(maxLength, userProc, extraArgArray, argPtrArray, numArgsPtr,
  743.          argList, realLengthPtr, paddedLengthPtr)
  744.     int         maxLength;        /* The maximum length of one argument */
  745.     Boolean  userProc;        /* Set if the calling process is a user 
  746.                       * process. */
  747.     char     **extraArgArray;    /* Any arguments that should be
  748.                        * inserted prior to argv[1] */
  749.     char     **argPtrArray;    /* The array of argument pointers. */
  750.     int         *numArgsPtr;    /* Pointer to the number of arguments in the
  751.                  * argArray. This is updated with the
  752.                  * actual number of arguments. */
  753.     List_Links *argList;    /* Pointer to header of list containing
  754.                  * copied data. Assumed to be initialized by
  755.                  * caller. */
  756.     int      *realLengthPtr;     /* Pointer to contain combined size, without
  757.                  * padding.   Value passed in contains
  758.                  * maximum. */
  759.     int      *paddedLengthPtr;     /* Pointer to contain combined size, including
  760.                  * padding. */
  761. {
  762.     int                 totalLength = 0;
  763.     int                 paddedTotalLength = 0;
  764.     int                 extraArgs;
  765.     Boolean                 accessible;
  766.     register    ArgListElement        *argListPtr;
  767.     register    char            **argPtr;
  768.     register    int            argNumber;
  769.     ReturnStatus            status;
  770.     char                *stringPtr;
  771.     int                    stringLength;
  772.     int                    realLength;
  773.     
  774.     if (extraArgArray != (char **) NIL) {
  775.     for (extraArgs = 0; extraArgArray[extraArgs] != (char *)NIL;
  776.          extraArgs++) {
  777.     }
  778.     } else {
  779.     extraArgs = 0;
  780.     }
  781.     
  782.     for (argNumber = 0, argPtr = argPtrArray; 
  783.      argNumber < *numArgsPtr;
  784.      argNumber++) {
  785.  
  786.     accessible = FALSE;
  787.  
  788.     if ((argNumber > 0 || argPtrArray == (char **) NIL) && extraArgs > 0) {
  789.         stringPtr = extraArgArray[0];
  790.         realLength = strlen(stringPtr) + 1;
  791.         extraArgArray++;
  792.         extraArgs--;
  793.     } else {
  794.         if (!userProc) {
  795.         if (*argPtr == (char *) NIL) {
  796.             break;
  797.         }
  798.         stringPtr = *argPtr;
  799.         stringLength = maxLength;
  800.         } else {
  801.         if (*argPtr == (char *) USER_NIL) {
  802.             break;
  803.         }
  804.         Vm_MakeAccessible(VM_READONLY_ACCESS,
  805.                   maxLength + 1, 
  806.                   (Address) *argPtr, 
  807.                   &stringLength,
  808.                   (Address *) &stringPtr);
  809.         if (stringLength == 0) {
  810.             status = SYS_ARG_NOACCESS;
  811.             goto execError;
  812.         }
  813.         accessible = TRUE;
  814.         }
  815.         /*
  816.          * Find out the length of the argument.  Because of accessibility
  817.          * limitations the whole string may not be available.
  818.          */
  819.         {
  820.         register char *charPtr;
  821.         for (charPtr = stringPtr, realLength = 0;
  822.              (realLength < stringLength) && (*charPtr != '\0');
  823.              charPtr++, realLength++) {
  824.         }
  825.         realLength++;
  826.         }
  827.         /*
  828.          * Move to the next argument.
  829.          */
  830.         argPtr++;
  831.     }
  832.  
  833.     /*
  834.      * Put this string onto the argument list.
  835.      */
  836.     argListPtr = (ArgListElement *)
  837.         malloc(sizeof(ArgListElement));
  838.     argListPtr->stringPtr =  malloc(realLength);
  839.     argListPtr->stringLen = realLength;
  840.     List_InitElement((List_Links *) argListPtr);
  841.     List_Insert((List_Links *) argListPtr, LIST_ATREAR(argList));
  842.     /*
  843.      * Calculate the room on the stack needed for this string.
  844.      * Make it double-word aligned to make access efficient on
  845.      * all machines.  Increment the amount needed to save the argument
  846.      * list (the same total length, but without the padding).
  847.      */
  848.     paddedTotalLength += Byte_AlignAddr(realLength);
  849.     totalLength += realLength;
  850.     /*
  851.      * Copy over the argument and ensure null termination.
  852.      */
  853.     bcopy((Address) stringPtr, (Address) argListPtr->stringPtr, realLength);
  854.     argListPtr->stringPtr[realLength-1] = '\0';
  855.     /*
  856.      * Clean up 
  857.      */
  858.     if (accessible) {
  859.         Vm_MakeUnaccessible((Address) stringPtr, stringLength);
  860.     }
  861.     if (realLength > maxLength+1) {
  862.         status = GEN_E2BIG;
  863.         goto execError;
  864.     }
  865.     }
  866.     if (realLengthPtr != (int *) NIL) {
  867.     if (totalLength > *realLengthPtr) {
  868.         /*
  869.          * Would really like to flag "argument too long" here.
  870.          * Also, should we check after every argument?
  871.          */
  872.         status = GEN_INVALID_ARG;
  873.         goto execError;
  874.     }
  875.     *realLengthPtr = totalLength;
  876.     }
  877.     if (paddedLengthPtr != (int *) NIL) {
  878.     *paddedLengthPtr = paddedTotalLength;
  879.     }
  880.     *numArgsPtr = argNumber;
  881.     return(SUCCESS);
  882.     
  883. execError:
  884.     /*
  885.      * We hit an error while copying in the arguments.  Free any
  886.      * arguments that were copied in.
  887.      */
  888.     while (!List_IsEmpty(argList)) {
  889.     argListPtr = (ArgListElement *) List_First(argList);
  890.     List_Remove((List_Links *) argListPtr);
  891.     free((Address) argListPtr->stringPtr);
  892.     free((Address) argListPtr);
  893.     }
  894.     return(status);
  895. }
  896.  
  897.  
  898. /*
  899.  *----------------------------------------------------------------------
  900.  *
  901.  * DoExec --
  902.  *
  903.  *    Exec a new program.  If the exec is to be done on this host, the
  904.  *    current process image is overlayed by the 
  905.  *    newly exec'd program.  If not, then set up the image of the
  906.  *    user stack and set *encapPtrPtr to point to it.
  907.  *
  908.  * Results:
  909.  *    In the local case, this routine does not return unless an
  910.  *    error occurs in which case the
  911.  *    error code is returned.  In the remote case, SUCCESS indicates
  912.  *    the remote exec may continue.
  913.  *
  914.  * Side effects:
  915.  *    The state of the calling process is modified for the new image and
  916.  *    the argPtrArray and envPtrArray are made unaccessible if this
  917.  *    is a user process.
  918.  *
  919.  *----------------------------------------------------------------------
  920.  */
  921.  
  922. static ReturnStatus
  923. DoExec(fileName, userArgsPtr, encapPtrPtr, debugMe)
  924.     char    fileName[];    /* The name of the file that is to be exec'd */
  925.     UserArgs *userArgsPtr;    /* Information for taking args
  926.                  * and environment, or NIL. */
  927.     ExecEncapState
  928.     **encapPtrPtr;        /* User stack state, either for us to use,
  929.                  * for us to set, or NIL */
  930.     Boolean    debugMe;    /* TRUE means that the process is to be 
  931.                  * sent a SIG_DEBUG signal before
  932.                      * executing its first instruction. */
  933. {
  934.     register    Proc_ControlBlock    *procPtr;
  935.     Vm_ExecInfo                *execInfoPtr;
  936.     Vm_ExecInfo                execInfo;
  937.     Vm_Segment                *codeSegPtr = (Vm_Segment *) NIL;
  938.     char                *argString = (char *) NIL;
  939.     char                *argStringSave;
  940.     Address                argBuffer = (Address) NIL;
  941.     Fs_Stream                *filePtr;
  942.     ReturnStatus            status;
  943.     char                buffer[PROC_MAX_INTERPRET_SIZE];
  944.     int                    extraArgs = 0;
  945.     char                *shellArgPtr;
  946.     char                *extraArgsArray[2];
  947.     char                **extraArgsPtrPtr;
  948.     int                    argBytes;
  949.     Address                userStackPointer;
  950.     Boolean                usedFile;
  951.     int                    uid = -1;
  952.     int                    gid = -1;
  953.     ExecEncapState            *encapPtr;
  954.     int                    importing = 0;
  955.     int                    exporting = 0;
  956.     ProcObjInfo                objInfo;
  957.  
  958. #ifdef notdef
  959.     DBG_CALL;
  960. #endif
  961.  
  962.     /*
  963.      * Use the encapsulation buffer and arguments arrays to determine
  964.      * whether everything is local, or we're starting a remote exec,
  965.      * or finishing one from another host.
  966.      */
  967.     if (encapPtrPtr != (ExecEncapState **) NIL) {
  968.     if (userArgsPtr != (UserArgs *) NIL) {
  969.         exporting = TRUE;
  970.     } else {
  971.         importing = TRUE;
  972.     }
  973.     }
  974.     procPtr = Proc_GetActualProc();
  975.  
  976.     /*
  977.      * objInfo.unixCompat is set if the header of the file indicates
  978.      * it is a Unix binary.
  979.      */
  980.     objInfo.unixCompat = 0;
  981.     procPtr->unixProgress = PROC_PROGRESS_NOT_UNIX;
  982.  
  983.     /* Turn off profiling */
  984.     if (procPtr->Prof_Scale != 0) {
  985.     Prof_Disable(procPtr);
  986.     }
  987.  
  988.     /*
  989.      * Save the argString away, because if we hit an error we always
  990.      * set procPtr->argString back to this value.
  991.      */
  992.     argStringSave = procPtr->argString;
  993.  
  994.     /*
  995.      * Open the file that is to be exec'd.
  996.      */
  997.     filePtr = (Fs_Stream *) NIL;
  998.     status =  Fs_Open(fileName, FS_EXECUTE | FS_FOLLOW, FS_FILE, 0, &filePtr);
  999.     if (status != SUCCESS) {
  1000.     filePtr = (Fs_Stream *) NIL;
  1001.     goto execError;
  1002.     }
  1003.  
  1004.     /*
  1005.      * Determine if this file has the set uid or set gid bits set.
  1006.      */
  1007.     Fs_CheckSetID(filePtr, &uid, &gid);
  1008.  
  1009.     /*
  1010.      * See if this file is already cached by the virtual memory system.
  1011.      */
  1012.     execInfoPtr = (Vm_ExecInfo *)NIL;
  1013.     codeSegPtr = Vm_FindCode(filePtr, procPtr, &execInfoPtr, &usedFile);
  1014.     if (codeSegPtr == (Vm_Segment *) NIL) {
  1015.     int    sizeRead;
  1016.  
  1017.     /*
  1018.      * Read the file header.
  1019.      */
  1020.     sizeRead = PROC_MAX_INTERPRET_SIZE > sizeof(ProcExecHeader) ?
  1021.                         PROC_MAX_INTERPRET_SIZE :
  1022.                         sizeof(ProcExecHeader);
  1023.     status = Fs_Read(filePtr, buffer, 0, &sizeRead);
  1024.     if (status != SUCCESS) {
  1025.         goto execError;
  1026.     }
  1027.     if (sizeRead >= 2 && buffer[0] == '#' && buffer[1] == '!') {
  1028.         Vm_InitCode(filePtr, (Vm_Segment *) NIL, (Vm_ExecInfo *) NIL);
  1029.         /*
  1030.          * See if this is an interpreter file.
  1031.          */
  1032.         status = SetupInterpret(buffer, sizeRead, &filePtr, 
  1033.                     &shellArgPtr, &extraArgs, &objInfo); 
  1034.         if (status != SUCCESS) {
  1035.         filePtr = (Fs_Stream *)NIL;
  1036.         goto execError;
  1037.         }
  1038.         codeSegPtr = Vm_FindCode(filePtr, procPtr, &execInfoPtr, &usedFile);
  1039.     } else {
  1040.         if (sizeRead < sizeof(ProcExecHeader) ||
  1041.         ProcGetObjInfo(filePtr, (ProcExecHeader *)buffer, &objInfo) != SUCCESS) {
  1042.             if(ProcIsObj(filePtr,1)==SUCCESS) {
  1043.             status = FS_NO_ACCESS;
  1044.             } else {
  1045.             status = PROC_BAD_AOUT_FORMAT;
  1046.             }
  1047.         goto execError;
  1048.         }
  1049.     }
  1050.     }
  1051.  
  1052.     if (!importing) {
  1053.     /*
  1054.      * Set up whatever special arguments we might have due to an
  1055.      * interpreter file.  If the
  1056.      */
  1057.     if (extraArgs > 0) {
  1058.         int i;
  1059.         int index;
  1060.  
  1061.         if (userArgsPtr->argPtrArray == (char **) NIL) {
  1062.         extraArgsArray[0] = fileName;
  1063.         index = 1;
  1064.         } else {
  1065.         index = 0;
  1066.         }
  1067.         for (i = index; extraArgs > 0; i++, extraArgs--) {
  1068.         if (extraArgs == 2) {
  1069.             extraArgsArray[i] = shellArgPtr;
  1070.         } else {
  1071.             extraArgsArray[i] = fileName;
  1072.         }
  1073.         }
  1074.         extraArgsArray[i] = (char *) NIL;
  1075.         extraArgsPtrPtr = extraArgsArray;
  1076.     } else {
  1077.         extraArgsPtrPtr = (char **) NIL;
  1078.     }
  1079.     /*
  1080.      * Copy in the argument list and environment into a single contiguous
  1081.      * buffer.
  1082.      */
  1083.     status = SetupArgs(userArgsPtr, extraArgsPtrPtr,
  1084.                &argBuffer, &argString);
  1085.  
  1086.     if (status != SUCCESS) {
  1087.         goto execError;
  1088.     }
  1089.  
  1090.     /*
  1091.      * We no longer need access to the old arguments or the environment. 
  1092.      */
  1093.     if (userArgsPtr->userMode) {
  1094.         if (userArgsPtr->argPtrArray != (char **) NIL) {
  1095.         Vm_MakeUnaccessible((Address) userArgsPtr->argPtrArray,
  1096.                     userArgsPtr->argLength);
  1097.         userArgsPtr->argPtrArray = (char **)NIL;
  1098.         userArgsPtr->argLength = 0;
  1099.         }
  1100.         if (userArgsPtr->envPtrArray != (char **) NIL) {
  1101.         Vm_MakeUnaccessible((Address) userArgsPtr->envPtrArray,
  1102.                     userArgsPtr->envLength);
  1103.         userArgsPtr->envPtrArray = (char **)NIL;
  1104.         userArgsPtr->envLength = 0;
  1105.         }
  1106.     }
  1107.  
  1108.     /*
  1109.      * Close any streams that have been marked close-on-exec.
  1110.      */
  1111.     Fs_CloseOnExec(procPtr);
  1112.     } else {
  1113.     /*
  1114.      * We're "importing" this process.  Use the stack copied over from
  1115.      * its former host.
  1116.      */
  1117.     argBuffer = procPtr->remoteExecBuffer;
  1118.     procPtr->remoteExecBuffer = (Address) NIL;
  1119.     encapPtr = (ExecEncapState *) argBuffer;
  1120.     argString = encapPtr->hdr.argString;
  1121.     }
  1122.     
  1123.     /*
  1124.      * Change the argument string.
  1125.      */
  1126.     procPtr->argString = argString;
  1127.     /*
  1128.      * Do set uid here.  This way, the uid will be set before a remote
  1129.      * exec.
  1130.      */
  1131.     if (uid != -1) {
  1132.     procPtr->effectiveUserID = uid;
  1133.     }
  1134.     /*
  1135.      * If we're doing the initial part of a remote exec, time to
  1136.      * return to our caller.  Free up whatever virtual memory resources
  1137.      * we had set up.
  1138.      */
  1139.     encapPtr = (ExecEncapState *) argBuffer;
  1140.     if (exporting) {
  1141.     if (filePtr != (Fs_Stream *) NIL) {
  1142.         if (codeSegPtr != (Vm_Segment *) NIL) {
  1143.         Vm_SegmentDelete(codeSegPtr, procPtr);
  1144.         if (!usedFile) {
  1145.             /*
  1146.              * If usedFile is TRUE then the file has already been closed
  1147.              * by Vm_SegmentDelete.
  1148.              */
  1149.             (void) Fs_Close(filePtr);
  1150.         }
  1151.         } else {
  1152.         /*
  1153.          * We're not setting up the segment after all, so let vm
  1154.          * clean up state and wake up anyone waiting for us to
  1155.          * set up the segment.
  1156.          */
  1157.         Vm_InitCode(filePtr, (Vm_Segment *) NIL, (Vm_ExecInfo *) NIL);
  1158.         (void) Fs_Close(filePtr);
  1159.         }
  1160.     }
  1161.     *encapPtrPtr = encapPtr;
  1162.     encapPtr->hdr.fileName = fileName;
  1163.     encapPtr->hdr.argString = argString;
  1164.     return(SUCCESS);
  1165.     }
  1166.     /*
  1167.      * The file name has been dynamically allocated if it was copied in
  1168.      * on this host from user space.
  1169.      */
  1170.     if (!importing && userArgsPtr->userMode) {
  1171.     free(fileName);
  1172.     fileName = (char *) NIL;
  1173.     }
  1174.     /*
  1175.      * Set up virtual memory for the new image.
  1176.      */
  1177.     if (execInfoPtr == (Vm_ExecInfo *)NIL) {
  1178.     execInfoPtr = &execInfo;
  1179.     }
  1180.     if (!SetupVM(procPtr, &objInfo, filePtr, usedFile, &codeSegPtr, 
  1181.          execInfoPtr)) {
  1182.     /*
  1183.      * Setup VM will make sure that the file is closed and that
  1184.      * all new segments are freed up.
  1185.      */
  1186.     filePtr = (Fs_Stream *) NIL;
  1187.     status = VM_NO_SEGMENTS;
  1188.     goto execError;
  1189.     }
  1190.  
  1191.     /*
  1192.      * Now copy all of the arguments and environment variables onto the stack.
  1193.      */
  1194.     argBytes = encapPtr->hdr.size - sizeof(ExecEncapHeader);
  1195.     userStackPointer = encapPtr->hdr.base;
  1196.     status = Vm_CopyOut(argBytes, (Address) &encapPtr->argc,
  1197.               userStackPointer);
  1198.  
  1199.     if (status != SUCCESS) {
  1200.     goto execError;
  1201.     }
  1202.  
  1203.     /*
  1204.      * Free original argString (kept in argStringSave, in case we
  1205.      * needed it) here, after last chance to goto execError.
  1206.      */
  1207.     if (argStringSave != (char *)NIL) {
  1208.     free(argStringSave);
  1209.     }
  1210.  
  1211.     /*
  1212.      * Set-gid only needs to be done on the host running the process.
  1213.      */
  1214.     if (gid != -1) {
  1215.     ProcAddToGroupList(procPtr, gid);
  1216.     }
  1217.  
  1218.     /*
  1219.      * Take signal actions for execed process.
  1220.      */
  1221.     Sig_Exec(procPtr);
  1222.     if (debugMe) {
  1223.     /*
  1224.      * Debugged processes get a SIG_DEBUG at start up.
  1225.      */
  1226.     Sig_SendProc(procPtr, SIG_DEBUG, SIG_NO_CODE, (Address)0);
  1227.     }
  1228.     if (!importing && (procPtr->genFlags & PROC_FOREIGN)) {
  1229.     ProcRemoteExec(procPtr, uid);
  1230.     }
  1231.     Proc_Unlock(procPtr);
  1232.  
  1233.     free(argBuffer);
  1234.     argBuffer = (Address) NIL;
  1235.     
  1236.     /*
  1237.      * Move the stack pointer on the sun4.
  1238.      */
  1239.     if (execInfoPtr->flags & UNIX_CODE) {
  1240. #ifdef sun4
  1241.     /*
  1242.      * Unix on the sun4 has the stack in a different location from
  1243.      * Sprite.
  1244.      */
  1245.     userStackPointer += 32;
  1246.     if (debugProcStubs) {
  1247.         printf("Moving stack pointer for Unix binary.\n");
  1248.     }
  1249. #endif
  1250.     procPtr->unixProgress = PROC_PROGRESS_UNIX;
  1251.     }
  1252.  
  1253.     /*
  1254.      * Disable interrupts.  Note that we don't use the macro DISABLE_INTR 
  1255.      * because there is an implicit enable interrupts when we return to user 
  1256.      * mode.
  1257.      */
  1258.     Mach_ExecUserProc(procPtr, userStackPointer, (Address) execInfoPtr->entry);
  1259.     panic("DoExec: Proc_RunUserProc returned.\n");
  1260.  
  1261. execError:
  1262.     /*
  1263.      * The exec failed after or while copying in the arguments.  Free any
  1264.      * virtual memory allocated and free any arguments or environment
  1265.      * variables that were copied in.
  1266.      */
  1267.     if (filePtr != (Fs_Stream *) NIL) {
  1268.     if (codeSegPtr != (Vm_Segment *) NIL) {
  1269.         Vm_SegmentDelete(codeSegPtr, procPtr);
  1270.         if (!usedFile) {
  1271.         /*
  1272.          * If usedFile is TRUE then the file has already been closed
  1273.          * by Vm_SegmentDelete.
  1274.          */
  1275.         (void) Fs_Close(filePtr);
  1276.         }
  1277.     } else {
  1278.         Vm_InitCode(filePtr, (Vm_Segment *) NIL, (Vm_ExecInfo *) NIL);
  1279.         (void) Fs_Close(filePtr);
  1280.     }
  1281.     }
  1282.     if (userArgsPtr != (UserArgs *) NIL && userArgsPtr->userMode) {
  1283.     if (userArgsPtr->argPtrArray != (char **) NIL) {
  1284.         Vm_MakeUnaccessible((Address) userArgsPtr->argPtrArray,
  1285.                 userArgsPtr->argLength);
  1286.         userArgsPtr->argPtrArray = (char **)NIL;
  1287.         userArgsPtr->argLength = 0;
  1288.     }
  1289.     if (userArgsPtr->envPtrArray != (char **) NIL) {
  1290.         Vm_MakeUnaccessible((Address) userArgsPtr->envPtrArray,
  1291.                 userArgsPtr->envLength);
  1292.         userArgsPtr->envPtrArray = (char **)NIL;
  1293.         userArgsPtr->envLength = 0;
  1294.     }
  1295.     }
  1296.     if (argBuffer != (Address) NIL) {
  1297.     free(argBuffer);
  1298.     }
  1299.     if (argString != (Address) NIL) {
  1300.     free(argString);
  1301.     }
  1302.     /*
  1303.      * Restore original arg string.  If we don't do this, then when
  1304.      * DoFork() tries to free() the arg string (after this process
  1305.      * exits, when some other process gets the then-empty process
  1306.      * slot), free() will panic because the original argString was
  1307.      * just freed above.
  1308.      */
  1309.     procPtr->argString = argStringSave;
  1310.  
  1311.     if (!importing && (fileName != (char *) NIL) && userArgsPtr->userMode) {
  1312.     free(fileName);
  1313.     fileName = (char *) NIL;
  1314.     }
  1315.     return(status);
  1316. }
  1317.  
  1318.  
  1319. /*
  1320.  *----------------------------------------------------------------------
  1321.  *
  1322.  * SetupInterpret --
  1323.  *
  1324.  *    Read in the interpreter name, arguments and object file header.
  1325.  *
  1326.  * Results:
  1327.  *    Error if for some reason could not parse the interpreter name
  1328.  *    and arguments are could not open the interpreter object file.
  1329.  *
  1330.  * Side effects:
  1331.  *    *filePtrPtr contains pointer to the interpreter object file, 
  1332.  *    *argPtrPtr points to interpreter argument string, *extraArgsPtr
  1333.  *    contains number of arguments that have to be prepended to the 
  1334.  *    argument vector passed to the interpreter and *aoutPtr contains the
  1335.  *    interpreter files a.out header.
  1336.  *
  1337.  *----------------------------------------------------------------------
  1338.  */ 
  1339.  
  1340. static ReturnStatus
  1341. SetupInterpret(buffer, sizeRead, filePtrPtr, argPtrPtr, 
  1342.            extraArgsPtr, objInfoPtr)
  1343.     register    char    *buffer;    /* Bytes read in from file.*/
  1344.     int            sizeRead;    /* Number of bytes in buffer. */    
  1345.     register    Fs_Stream **filePtrPtr;    /* IN/OUT parameter: Exec'd file as 
  1346.                      * input, interpreter file as output. */
  1347.     char        **argPtrPtr;    /* Pointer to shell argument string. */
  1348.     int            *extraArgsPtr;    /* Number of arguments that have to be
  1349.                      * added for the intepreter. */
  1350.     ProcObjInfo        *objInfoPtr;    /* Place to put obj file info. */
  1351. {
  1352.     register    char    *strPtr;
  1353.     char        *shellNamePtr;
  1354.     int            i;
  1355.     ReturnStatus    status;
  1356.     ProcExecHeader    execHeader;
  1357.  
  1358.     (void) Fs_Close(*filePtrPtr);
  1359.  
  1360.     /*
  1361.      * Make sure the interpreter name and arguments are terminated by a 
  1362.      * carriage return.
  1363.      */
  1364.     for (i = 2, strPtr = &(buffer[2]);
  1365.      i < sizeRead && *strPtr != '\n';
  1366.      i++, strPtr++) {
  1367.     }
  1368.     if (i == sizeRead) {
  1369.     return(PROC_BAD_FILE_NAME);
  1370.     }
  1371.     *strPtr = '\0';
  1372.  
  1373.     /*
  1374.      * Get a pointer to the name of the file to exec.
  1375.      */
  1376.  
  1377.     for (strPtr = &(buffer[2]); isspace(*strPtr); strPtr++) {
  1378.     }
  1379.     if (*strPtr == '\0') {
  1380.     return(PROC_BAD_FILE_NAME);
  1381.     }
  1382.     shellNamePtr = strPtr;
  1383.     while (!isspace(*strPtr) && *strPtr != '\0') {
  1384.     strPtr++;
  1385.     }
  1386.     *extraArgsPtr = 1;
  1387.  
  1388.     /*
  1389.      * Get a pointer to the arguments if there are any.
  1390.      */
  1391.  
  1392.     if (*strPtr != '\0') {
  1393.     *strPtr = '\0';
  1394.     strPtr++;
  1395.     while (isspace(*strPtr)) {
  1396.         strPtr++;
  1397.     }
  1398.     if (*strPtr != '\0') {
  1399.         *argPtrPtr = strPtr;
  1400.         *extraArgsPtr = 2;
  1401.     }
  1402.     }
  1403.  
  1404.     /*
  1405.      * Open the interpreter to exec and read the a.out header.
  1406.      */
  1407.  
  1408.     status = Fs_Open(shellNamePtr, FS_EXECUTE | FS_FOLLOW, FS_FILE, 0,
  1409.              filePtrPtr);
  1410.     if (status != SUCCESS) {
  1411.     return(status);
  1412.     }
  1413.  
  1414.     sizeRead = sizeof(ProcExecHeader);
  1415.     status = Fs_Read(*filePtrPtr, (Address)&execHeader, 0, &sizeRead);
  1416.     if (status == SUCCESS && sizeRead != sizeof(ProcExecHeader)) {
  1417.     status = PROC_BAD_AOUT_FORMAT;
  1418.     } else {
  1419.     status = ProcGetObjInfo(*filePtrPtr, &execHeader, objInfoPtr);
  1420.     }
  1421.     if (status != SUCCESS) {
  1422.     if(ProcIsObj(*filePtrPtr,1)==SUCCESS) {
  1423.         status = FS_NO_ACCESS;
  1424.     } else {
  1425.         status = PROC_BAD_AOUT_FORMAT;
  1426.     }
  1427.     (void) Fs_Close(*filePtrPtr);
  1428.     }
  1429.     return(status);
  1430. }
  1431.  
  1432. /*
  1433.  *----------------------------------------------------------------------
  1434.  *
  1435.  * SetupVM --
  1436.  *
  1437.  *    Setup virtual memory for this process.
  1438.  *
  1439.  * Results:
  1440.  *    TRUE if could set up VM, false otherwise.
  1441.  *
  1442.  * Side effects:
  1443.  *    *filePtrPtr contains pointer to the interpreter object file, 
  1444.  *    *argPtrPtr points to interpreter argument string, *extraArgsPtr
  1445.  *    contains number of arguments that have to be prepended to the 
  1446.  *    argument vector passed to the interpreter and *aoutPtr contains the
  1447.  *    interpreter files a.out header.
  1448.  *
  1449.  *----------------------------------------------------------------------
  1450.  */ 
  1451. static Boolean
  1452. SetupVM(procPtr, objInfoPtr, codeFilePtr, usedFile, codeSegPtrPtr, execInfoPtr)
  1453.     register    Proc_ControlBlock    *procPtr;
  1454.     register    ProcObjInfo        *objInfoPtr;
  1455.     Fs_Stream                *codeFilePtr;
  1456.     Boolean                usedFile;
  1457.     Vm_Segment                **codeSegPtrPtr;
  1458.     register    Vm_ExecInfo        *execInfoPtr;
  1459. {
  1460.     register    Vm_Segment    *segPtr;
  1461.     int                numPages;
  1462.     int                fileOffset;
  1463.     int                pageOffset;
  1464.     Boolean            notFound;
  1465.     Vm_Segment            *heapSegPtr;
  1466.     Fs_Stream            *heapFilePtr;
  1467.     Address            heapEnd = (Address) NIL;
  1468.     int                realCode = 1;
  1469.  
  1470.     if (*codeSegPtrPtr == (Vm_Segment *) NIL) {
  1471.     if (objInfoPtr->unixCompat) {
  1472.         execInfoPtr->flags = UNIX_CODE;
  1473.     } else {
  1474.         execInfoPtr->flags = 0;
  1475.     }
  1476.     execInfoPtr->entry = (int)objInfoPtr->entry;
  1477.     if (objInfoPtr->heapSize != 0) {
  1478.         execInfoPtr->heapPages = 
  1479.             (objInfoPtr->heapSize - 1) / vm_PageSize + 1;
  1480.     } else { 
  1481.         execInfoPtr->heapPages = 0;
  1482.     }
  1483.     if (objInfoPtr->bssSize != 0) {
  1484.         execInfoPtr->heapPages += 
  1485.             (objInfoPtr->bssSize - 1) / vm_PageSize + 1;
  1486.     }
  1487.     execInfoPtr->heapPageOffset = 
  1488.             (unsigned)objInfoPtr->heapLoadAddr / vm_PageSize;
  1489.     execInfoPtr->heapFileOffset = objInfoPtr->heapFileOffset;
  1490.     heapEnd = objInfoPtr->heapLoadAddr + objInfoPtr->heapSize;
  1491.     execInfoPtr->heapExcess =
  1492.         vm_PageSize - ((unsigned)heapEnd&(vm_PageSize-1));
  1493.     if (execInfoPtr->heapExcess == vm_PageSize) {
  1494.         execInfoPtr->heapExcess = 0;
  1495.     }
  1496.     execInfoPtr->bssFirstPage = 
  1497.             (unsigned)objInfoPtr->bssLoadAddr / vm_PageSize;
  1498.     if ((unsigned)(heapEnd-1) / vm_PageSize >= execInfoPtr->bssFirstPage) {
  1499.         /*
  1500.          * End of heap, start of bss in same page, so move bss.
  1501.          */
  1502.         execInfoPtr->bssFirstPage = (unsigned)(heapEnd-1)/vm_PageSize + 1;
  1503.     }
  1504.  
  1505.     if (objInfoPtr->bssSize != 0) {
  1506.         execInfoPtr->bssLastPage = (int) (execInfoPtr->bssFirstPage + 
  1507.                    (objInfoPtr->bssSize - 1) / vm_PageSize);
  1508.     } else {
  1509.         execInfoPtr->bssLastPage = 0;
  1510.     }
  1511.     /* 
  1512.      * Set up the code image.
  1513.      */
  1514.     if (objInfoPtr->codeSize == 0) {
  1515.         /*
  1516.          * Things work better if we have a code segment.
  1517.          */
  1518.         realCode = 0;
  1519.         objInfoPtr->codeSize = vm_PageSize;
  1520.     }
  1521.     numPages = (objInfoPtr->codeSize - 1) / vm_PageSize + 1;
  1522.     fileOffset = objInfoPtr->codeFileOffset;
  1523.     pageOffset = (unsigned)objInfoPtr->codeLoadAddr / vm_PageSize;
  1524.     segPtr = Vm_SegmentNew(VM_CODE, codeFilePtr, fileOffset,
  1525.                    numPages, pageOffset, procPtr);
  1526.     if (segPtr == (Vm_Segment *) NIL) {
  1527.         Vm_InitCode(codeFilePtr, (Vm_Segment *) NIL, (Vm_ExecInfo *) NIL);
  1528.         (void) Fs_Close(codeFilePtr);
  1529.         return(FALSE);
  1530.     }
  1531.     Vm_ValidatePages(segPtr, pageOffset, pageOffset + numPages - 1,
  1532.              FALSE, TRUE);
  1533.     if (realCode) {
  1534.         Vm_InitCode(codeFilePtr, segPtr, execInfoPtr);
  1535.     } else {
  1536.         Vm_InitCode(codeFilePtr, (Vm_Segment *) NIL, (Vm_ExecInfo *) NIL);
  1537.     }
  1538.     *codeSegPtrPtr = segPtr;
  1539.     notFound = TRUE;
  1540.     } else {
  1541.     notFound = FALSE;
  1542.     }
  1543.  
  1544.     if (usedFile || notFound) {
  1545.     Fsio_StreamCopy(codeFilePtr, &heapFilePtr);
  1546.     } else {
  1547.     heapFilePtr = codeFilePtr;
  1548.     }
  1549.     /* 
  1550.      * Set up the heap image.
  1551.      */
  1552.     segPtr = Vm_SegmentNew(VM_HEAP, heapFilePtr, execInfoPtr->heapFileOffset,
  1553.                    execInfoPtr->heapPages, 
  1554.                    execInfoPtr->heapPageOffset, procPtr);
  1555.     if (segPtr == (Vm_Segment *) NIL) {
  1556.     Vm_SegmentDelete(*codeSegPtrPtr, procPtr);
  1557.     (void) Fs_Close(heapFilePtr);
  1558.     return(FALSE);
  1559.     }
  1560.     Vm_ValidatePages(segPtr, execInfoPtr->heapPageOffset,
  1561.              execInfoPtr->bssFirstPage - 1, FALSE, TRUE);
  1562.     if (execInfoPtr->bssLastPage > 0) {
  1563.     Vm_ValidatePages(segPtr, execInfoPtr->bssFirstPage,
  1564.              execInfoPtr->bssLastPage, TRUE, TRUE);
  1565.     }
  1566.     heapSegPtr = segPtr;
  1567.     /*
  1568.      * Set up a new stack.
  1569.      */
  1570.     segPtr = Vm_SegmentNew(VM_STACK, (Fs_Stream *) NIL, 0, 
  1571.                1, mach_LastUserStackPage, procPtr);
  1572.     if (segPtr == (Vm_Segment *) NIL) {
  1573.     Vm_SegmentDelete(*codeSegPtrPtr, procPtr);
  1574.     Vm_SegmentDelete(heapSegPtr, procPtr);
  1575.     return(FALSE);
  1576.     }
  1577.     Vm_ValidatePages(segPtr, mach_LastUserStackPage, 
  1578.             mach_LastUserStackPage, TRUE, TRUE);
  1579.  
  1580.     Proc_Lock(procPtr);
  1581.     procPtr->genFlags |= PROC_NO_VM;
  1582. #ifdef sun4
  1583.     Mach_FlushWindowsToStack();
  1584.     VmMach_FlushCurrentContext();
  1585. #endif
  1586.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_CODE], procPtr);
  1587.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_HEAP], procPtr);
  1588.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_STACK], procPtr);
  1589.     procPtr->vmPtr->segPtrArray[VM_CODE] = *codeSegPtrPtr;
  1590.     procPtr->vmPtr->segPtrArray[VM_HEAP] = heapSegPtr;
  1591.     procPtr->vmPtr->segPtrArray[VM_STACK] = segPtr;
  1592.     procPtr->genFlags &= ~PROC_NO_VM;
  1593.     VmMach_ReinitContext(procPtr);
  1594.  
  1595.     /*
  1596.      * If heap does not match page boundary, prefetch the partial page
  1597.      * if necessary, and zero the rest.
  1598.      */
  1599.     if (execInfoPtr->heapExcess != 0) {
  1600.     if (realCode && (execInfoPtr->flags & UNIX_CODE) == 0) {
  1601.         printf("SetupVM: Warning: Program %s has unaligned heap %s\n",
  1602.             Fsutil_HandleName(&codeFilePtr->hdr),
  1603.             "and should be relinked");
  1604.     }
  1605.     return ZeroHeapEnd(execInfoPtr);
  1606.     }
  1607.     return(TRUE);
  1608. }
  1609.  
  1610.  
  1611. /*
  1612.  *----------------------------------------------------------------------
  1613.  *
  1614.  * ZeroHeapEnd --
  1615.  *
  1616.  *    Zero out the end of the heap (from the given address to the 
  1617.  *    next page boundary).  This routine exists for compatibility 
  1618.  *    with oddly-linked binaries.
  1619.  *
  1620.  * Results:
  1621.  *    TRUE if we were successful, FALSE if not (e.g., couldn't bring 
  1622.  *    in the last heap page).
  1623.  *
  1624.  * Side effects:
  1625.  *    None.
  1626.  *
  1627.  *----------------------------------------------------------------------
  1628.  */
  1629.     
  1630. static Boolean
  1631. ZeroHeapEnd(execInfoPtr)
  1632.     Vm_ExecInfo    *execInfoPtr;    /* info about the exec file */
  1633. {
  1634.     ReturnStatus    status;
  1635.     Address    heapEnd;    /* kernel address of end of heap */
  1636.     int        bytesToZero;    /* number of bytes to zero out */
  1637.     int        bytesAvail;    /* number of bytes accessible */
  1638.     int        userHeapEnd;
  1639.     
  1640.  
  1641.     status = Vm_PageIn((Address) ((execInfoPtr->bssFirstPage-1)*vm_PageSize),
  1642.                FALSE);
  1643.     if (status != SUCCESS) {
  1644.     printf("SetupVM: heap prefetch failure\n");
  1645.     return FALSE;
  1646.     }
  1647.     bytesToZero = execInfoPtr->heapExcess;
  1648.     userHeapEnd = execInfoPtr->bssFirstPage*vm_PageSize-bytesToZero;
  1649.     if (debugProcStubs) {
  1650.     printf("ZeroHeapEnd: zeroing %x at %x\n", bytesToZero, userHeapEnd);
  1651.     }
  1652.     Vm_MakeAccessible(VM_READWRITE_ACCESS, bytesToZero, (Address)userHeapEnd,
  1653.               &bytesAvail, (Address *)&heapEnd);
  1654.     if (bytesAvail != bytesToZero) {
  1655.     printf("SetupVM: can't map heap\n");
  1656.     return FALSE;
  1657.     }
  1658.     bzero((char *)heapEnd, bytesToZero);
  1659.     Vm_MakeUnaccessible(heapEnd, bytesToZero);
  1660.  
  1661.     return TRUE;
  1662. }
  1663.  
  1664.  
  1665. /*
  1666.  *----------------------------------------------------------------------
  1667.  *
  1668.  * ProcExecGetEncapSize --
  1669.  *
  1670.  *    Return the size of the encapsulated exec state.
  1671.  *
  1672.  * Results:
  1673.  *    SUCCESS is returned directly; the size of the encapsulated state
  1674.  *    is returned in infoPtr->size.
  1675.  *
  1676.  * Side effects:
  1677.  *    None.
  1678.  *
  1679.  *----------------------------------------------------------------------
  1680.  */
  1681.  
  1682. /* ARGSUSED */
  1683. ReturnStatus
  1684. ProcExecGetEncapSize(procPtr, hostID, infoPtr)
  1685.     Proc_ControlBlock *procPtr;            /* process being migrated */
  1686.     int hostID;                    /* host to which it migrates */
  1687.     Proc_EncapInfo *infoPtr;            /* area w/ information about
  1688.                          * encapsulated state */
  1689. {
  1690.     ExecEncapState *encapPtr;
  1691.  
  1692.     encapPtr = (ExecEncapState *) procPtr->remoteExecBuffer;
  1693.     encapPtr->hdr.fileNameLength =
  1694.     Byte_AlignAddr(strlen(encapPtr->hdr.fileName) + 1);
  1695.     encapPtr->hdr.argLength =
  1696.     Byte_AlignAddr(strlen(encapPtr->hdr.argString) + 1);
  1697.     infoPtr->size = encapPtr->hdr.size + encapPtr->hdr.fileNameLength +
  1698.     encapPtr->hdr.argLength;
  1699.     return(SUCCESS);    
  1700. }
  1701.  
  1702.  
  1703. /*
  1704.  *----------------------------------------------------------------------
  1705.  *
  1706.  * ProcExecEncapState --
  1707.  *
  1708.  *    Encapsulate the information needed to perform a remote exec,
  1709.  *    and return it in the buffer provided.
  1710.  *
  1711.  * Results:
  1712.  *    SUCCESS.  The buffer is filled.
  1713.  *
  1714.  * Side effects:
  1715.  *    None.
  1716.  *----------------------------------------------------------------------
  1717.  */
  1718.  
  1719. /* ARGSUSED */
  1720. ReturnStatus
  1721. ProcExecEncapState(procPtr, hostID, infoPtr, bufPtr)
  1722.     register Proc_ControlBlock     *procPtr;  /* The process being migrated */
  1723.     int hostID;                   /* host to which it migrates */
  1724.     Proc_EncapInfo *infoPtr;           /* area w/ information about
  1725.                         * encapsulated state */
  1726.     Address bufPtr;               /* Pointer to allocated buffer */
  1727. {
  1728.     ExecEncapState *encapPtr;
  1729.  
  1730.     encapPtr = (ExecEncapState *) procPtr->remoteExecBuffer;
  1731.  
  1732.     bcopy((Address) encapPtr, bufPtr, encapPtr->hdr.size);
  1733.     bufPtr += encapPtr->hdr.size;
  1734.     (void) strncpy(bufPtr, encapPtr->hdr.fileName, encapPtr->hdr.fileNameLength);
  1735.     bufPtr += encapPtr->hdr.fileNameLength;
  1736.     (void) strncpy(bufPtr, encapPtr->hdr.argString, encapPtr->hdr.argLength);
  1737.     return(SUCCESS);
  1738. }
  1739.  
  1740.  
  1741. /*
  1742.  *----------------------------------------------------------------------
  1743.  *
  1744.  * ProcExecDeencapState --
  1745.  *
  1746.  *    Get remote exec information from a Proc_ControlBlock from another host.
  1747.  *    The information is contained in the parameter ``buffer''.
  1748.  *
  1749.  * Results:
  1750.  *    SUCCESS.
  1751.  *
  1752.  * Side effects:
  1753.  *    Memory is allocated for argString, which is kept around while the
  1754.  *    process is alive.
  1755.  *----------------------------------------------------------------------
  1756.  */
  1757.  
  1758. /* ARGSUSED */
  1759. ReturnStatus
  1760. ProcExecDeencapState(procPtr, infoPtr, bufPtr)
  1761.     register Proc_ControlBlock     *procPtr; /* The process being migrated */
  1762.     Proc_EncapInfo *infoPtr;          /* information about the buffer */
  1763.     Address bufPtr;              /* buffer containing data */
  1764. {
  1765.     ExecEncapState *encapPtr;
  1766.     char *argString;
  1767.  
  1768.     procPtr->remoteExecBuffer = malloc(infoPtr->size);
  1769.     bcopy(bufPtr, procPtr->remoteExecBuffer, infoPtr->size);
  1770.  
  1771.     encapPtr = (ExecEncapState *) procPtr->remoteExecBuffer;
  1772.     encapPtr->hdr.fileName = procPtr->remoteExecBuffer + encapPtr->hdr.size;
  1773.     argString = encapPtr->hdr.fileName + encapPtr->hdr.fileNameLength;
  1774.     encapPtr->hdr.argString = malloc(encapPtr->hdr.argLength);
  1775.     (void) strncpy(encapPtr->hdr.argString, argString, encapPtr->hdr.argLength);
  1776.     return(SUCCESS);
  1777. }
  1778.  
  1779.  
  1780. /*
  1781.  *----------------------------------------------------------------------
  1782.  *
  1783.  * ProcExecFinishMigration --
  1784.  *
  1785.  *    Free up resources after a remote exec.  This includes buffers
  1786.  *      used to store information about a remote exec
  1787.  *    between the time of the system call and the time the migration
  1788.  *    completes: namely, the buffer containing the user's stack,
  1789.  *    and the file name to exec (reached via that buffer).  Also,
  1790.  *    free the virtual memory segments used by the process. 
  1791.  *
  1792.  * Results:
  1793.  *    SUCCESS.
  1794.  *
  1795.  * Side effects:
  1796.  *    Memory is freed. The segments are freed.
  1797.  *----------------------------------------------------------------------
  1798.  */
  1799.  
  1800. /* ARGSUSED */
  1801. ReturnStatus
  1802. ProcExecFinishMigration(procPtr, hostID, infoPtr, bufPtr, failure)
  1803.     register Proc_ControlBlock     *procPtr; /* The process being migrated */
  1804.     int hostID;                  /* Host to which it migrated */
  1805.     Proc_EncapInfo *infoPtr;          /* Information about the buffer */
  1806.     Address bufPtr;              /* Buffer containing data */
  1807.     Boolean failure;              /* Whether a failure occurred */
  1808. {
  1809.     ExecEncapState *encapPtr;
  1810.     int i;
  1811.  
  1812.     encapPtr = (ExecEncapState *) procPtr->remoteExecBuffer;
  1813.     free(encapPtr->hdr.fileName);
  1814.     free(procPtr->remoteExecBuffer);
  1815.     Proc_Lock(procPtr);
  1816.     procPtr->remoteExecBuffer = (Address) NIL;
  1817.     procPtr->genFlags |= PROC_NO_VM;
  1818.     Proc_Unlock(procPtr);
  1819.     for (i = VM_CODE; i <= VM_STACK; i++) {
  1820.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[i], procPtr);
  1821.     }
  1822.     return(SUCCESS);
  1823. }
  1824.  
  1825.  
  1826. /*
  1827.  *----------------------------------------------------------------------
  1828.  *
  1829.  * ProcDoRemoteExec --
  1830.  *
  1831.  *    Do an exec of a process that's come to this machine from another
  1832.  *    one.  This is the PC at which the process resumes after migration,
  1833.  *    at which point it has no VM set up.
  1834.  *
  1835.  * Results:
  1836.  *    None.  This routine doesn't return, since upon error the process
  1837.  *    exits.
  1838.  *
  1839.  * Side effects:
  1840.  *    An exec is performed.
  1841.  *
  1842.  *----------------------------------------------------------------------
  1843.  */
  1844.  
  1845. void
  1846. ProcDoRemoteExec(procPtr)
  1847.     register Proc_ControlBlock *procPtr; /* Process control block, locked
  1848.                       * on entry */
  1849. {
  1850.     char *fileName = (char *) NIL;
  1851.     ReturnStatus status;
  1852.     ExecEncapState *encapPtr;
  1853.  
  1854.     /*
  1855.      * Set up dummy segments so that DoExec can work properly.
  1856.      */
  1857.  
  1858.     procPtr->genFlags &= ~PROC_REMOTE_EXEC_PENDING;
  1859.     procPtr->vmPtr->segPtrArray[VM_CODE] = 
  1860.                 Vm_SegmentNew(VM_CODE, (Fs_Stream *) NIL, 0,
  1861.                               1, 0, procPtr);
  1862.     if (procPtr->vmPtr->segPtrArray[VM_CODE] == (Vm_Segment *) NIL) {
  1863.     status = PROC_NO_SEGMENTS;
  1864.     Proc_Unlock(procPtr);
  1865.     goto failure;
  1866.     }
  1867.  
  1868.     procPtr->vmPtr->segPtrArray[VM_HEAP] =
  1869.             Vm_SegmentNew(VM_HEAP, (Fs_Stream *) NIL, 0, 1, 1, procPtr);
  1870.     if (procPtr->vmPtr->segPtrArray[VM_HEAP] == (Vm_Segment *) NIL) {
  1871.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_CODE], procPtr);
  1872.     status = PROC_NO_SEGMENTS;
  1873.     Proc_Unlock(procPtr);
  1874.     goto failure;
  1875.     }
  1876.  
  1877.     procPtr->vmPtr->segPtrArray[VM_STACK] =
  1878.             Vm_SegmentNew(VM_STACK, (Fs_Stream *) NIL, 
  1879.                    0 , 1, mach_LastUserStackPage, procPtr);
  1880.     if (procPtr->vmPtr->segPtrArray[VM_STACK] == (Vm_Segment *) NIL) {
  1881.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_CODE], procPtr);
  1882.     Vm_SegmentDelete(procPtr->vmPtr->segPtrArray[VM_HEAP], procPtr);
  1883.     status = PROC_NO_SEGMENTS;
  1884.     Proc_Unlock(procPtr);
  1885.     goto failure;
  1886.     }
  1887.  
  1888.     VmMach_ReinitContext(procPtr);
  1889.  
  1890.     encapPtr = (ExecEncapState *) procPtr->remoteExecBuffer;
  1891.     fileName = encapPtr->hdr.fileName;
  1892.     Proc_Unlock(procPtr);
  1893.     status = DoExec(fileName, (UserArgs *) NIL, &encapPtr, FALSE);
  1894.     /*
  1895.      * If the exec failed, then exit.  
  1896.      */
  1897.     failure:
  1898.     if (proc_MigDebugLevel > 0) {
  1899.     printf("Remote exec of %s failed: %s\n", fileName,
  1900.            Stat_GetMsg(status));
  1901.     }
  1902.     Proc_ExitInt(PROC_TERM_DESTROYED, SIG_KILL, 0);
  1903.     /*
  1904.      * NOTREACHED
  1905.      */
  1906. }
  1907.  
  1908.  
  1909. /*
  1910.  * The following table contains the functions to check if an executable
  1911.  * is of a particular machine type.
  1912.  */
  1913. int    hostFmt = HOST_FMT;
  1914. char * (*machType[]) _ARGS_((int bufferSize, char *buffer, int *magic, 
  1915.     int *syms, char **other)) =  {
  1916.     machType68k,
  1917.     machTypeSparc,
  1918.     machTypeSpur,
  1919.     machTypeMips,
  1920.     machTypeSymm,
  1921. };
  1922. /*
  1923.  *----------------------------------------------------------------------
  1924.  *
  1925.  * ProcIsObj -
  1926.  *
  1927.  *    Check if the process is an a.out file.  If doErr is set, an
  1928.  *    error message will be printed if the file is an a.out file.
  1929.  *    This routine is to be called if the file cannot be execed, to
  1930.  *    see if it's the wrong a.out type.
  1931.  *    This code is based on the Sprite a.out checking routines for
  1932.  *    the file program.
  1933.  *
  1934.  * Results:
  1935.  *    SUCCESS if the file is an a.out file.
  1936.  *    FAILURE if the file is not an a.out file.
  1937.  *
  1938.  * Side effects:
  1939.  *    An error may printed in the syslog if doErr is set.
  1940.  *
  1941.  *----------------------------------------------------------------------
  1942.  */
  1943. ReturnStatus
  1944. ProcIsObj(streamPtr, doErr)
  1945.     Fs_Stream    *streamPtr;    /* Stream pointer for obj file. */
  1946.     int        doErr;        /* 1 if want error messages. */
  1947. {
  1948.     ReturnStatus    status;
  1949.     char        *buffer;
  1950.     int            hdrSize = BUFSIZ;
  1951.     int            i;
  1952.     int            magic;
  1953.     char        *name;
  1954.     int            syms;
  1955.     char        *other;
  1956.  
  1957.     buffer = (char *)malloc(hdrSize);
  1958.     status = Fs_Read(streamPtr, (Address)buffer, 0, &hdrSize);
  1959.     if (status != SUCCESS) {
  1960.     return FAILURE;
  1961.     }
  1962.     for (i=0; i < sizeof(machType)/sizeof(*machType); i++) {
  1963.     name = machType[i](hdrSize, (const char *) buffer, &magic, &syms,
  1964.         &other);
  1965.     if (name != NULL) {
  1966.         if (doErr) {
  1967.         printf("Proc_Exec: Can't run %s ", name);
  1968.         switch (magic) {
  1969.             case 0407:
  1970.             printf("OMAGIC");
  1971.             break;
  1972.             case 0410:
  1973.             printf("NMAGIC");
  1974.             break;
  1975.             case 0413:
  1976.             printf("ZMAGIC");
  1977.             break;
  1978.             case 0414:
  1979.             printf("SPRITE_ZMAGIC");
  1980.             break;
  1981.             case 0415:
  1982.             printf("UNIX_ZMAGIC");
  1983.             break;
  1984.             case 0443:
  1985.             printf("LIBMAGIC");
  1986.             break;
  1987.             default:
  1988.             printf("(0%03o)", magic);
  1989.             break;
  1990.         }
  1991.         if (*other != '\0') {
  1992.             printf(" %s", other);
  1993.         }
  1994.         printf(" executable file on %s.\n", mach_MachineType);
  1995.         }
  1996.         return SUCCESS;
  1997.     }
  1998.     }
  1999.     return FAILURE;
  2000. }
  2001.